package cn.weekdragon.gscore.adapter.utils;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.cookie.Cookie;
import org.apache.hc.client5.http.cookie.CookieStore;
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
import org.apache.hc.client5.http.entity.mime.HttpMultipartMode;
import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.message.BasicNameValuePair;
import org.apache.hc.core5.net.URIBuilder;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Slf4j
public class HttpUtils {

    private static final CloseableHttpClient httpClient;
    static {
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        // 默认取消自动cookie管理
        httpClientBuilder.disableCookieManagement();
        httpClientBuilder.addExecInterceptorLast("log", (request, scope, chain) -> {
            Map<String,Object> logs = new HashMap<>();
            logs.put("url",request.getPath());
            logs.put("header",request.getHeaders());
            log.debug("网络请求：{}",JSON.toJSONString(logs));
            return chain.proceed(request, scope);
        });
        httpClient = httpClientBuilder.build();
    }

    public static String formGet(String urlStr, Map<String,Object> paramsMap) {
       return formGet(urlStr,paramsMap,null);
    }

    public static String buildUrlWithParams(String urlStr, Map<String, Object> paramsMap) {
        try {
            URL url = new URL(urlStr);
            List<NameValuePair> nvps = new ArrayList<>();
            if (MapUtil.isNotEmpty(paramsMap)) {
                for (Map.Entry<String, Object> stringObjectEntry : paramsMap.entrySet()) {
                    nvps.add(new BasicNameValuePair(stringObjectEntry.getKey(), stringObjectEntry.getValue().toString()));
                }
            }
            nvps.addAll(getQueryParams(urlStr));
            URI uri = new URIBuilder()
                    .setScheme(url.getProtocol())
                    .setHost(url.getHost())
                    .setPort(url.getPort())
                    .setPath(url.getPath())
                    // 构建参数
                    .setParameters(nvps)
                    .build();
            return uri.toString();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String formGet2(String urlStr,Map<String, Object> headers) {
       return formGet2(httpClient,urlStr,headers);
    }
    public static String formGet2(CloseableHttpClient httpClient,String urlStr,Map<String, Object> headers) {
        try {
            HttpGet httpGet = new HttpGet(urlStr);
            addHeader(httpGet, headers);
            CloseableHttpResponse closeableHttpResponse = httpClient.execute(httpGet);
            HttpEntity entity = closeableHttpResponse.getEntity();
            String res = IoUtil.read(entity.getContent(), StandardCharsets.UTF_8);
            closeableHttpResponse.close();
            return res;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String formGet(String urlStr, Map<String, Object> paramsMap, Map<String, Object> headers) {
        return formGet(httpClient,urlStr,paramsMap,headers);
    }

    public static String formGet(CloseableHttpClient httpClient,String urlStr, Map<String, Object> paramsMap, Map<String, Object> headers) {
        try {
            URL url = new URL(urlStr);
            List<NameValuePair> nvps = new ArrayList<>();
            if (MapUtil.isNotEmpty(paramsMap)) {
                for (Map.Entry<String, Object> stringObjectEntry : paramsMap.entrySet()) {
                    nvps.add(new BasicNameValuePair(stringObjectEntry.getKey(), stringObjectEntry.getValue().toString()));
                }
            }
            nvps.addAll(getQueryParams(urlStr));
            URI uri = new URIBuilder()
                    .setScheme(url.getProtocol())
                    .setHost(url.getHost())
                    .setPort(url.getPort())
                    .setPath(url.getPath())
                    // 构建参数
                    .setParameters(nvps)
                    .build();
            HttpGet httpGet = new HttpGet(uri);
            httpGet.setConfig(RequestConfig.custom().setConnectionRequestTimeout(10, TimeUnit.SECONDS).build());
            addHeader(httpGet, headers);
            CloseableHttpResponse closeableHttpResponse = httpClient.execute(httpGet);
            HttpEntity entity = closeableHttpResponse.getEntity();
            String res = IoUtil.read(entity.getContent(), StandardCharsets.UTF_8);
            closeableHttpResponse.close();
            return res;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String formRequest(String urlStr,String method, Map<String,Object> paramsMap,Map<String,Object> headers) {
        if("post".equalsIgnoreCase(method)){
            return formPost(urlStr,paramsMap,headers);
        }else{
            return formGet(urlStr,paramsMap,headers);
        }
    }

    public static String formPost(String urlStr, Map<String, Object> paramsMap, Map<String, Object> headers) {
        return formPost(httpClient,urlStr,paramsMap,headers);
    }

    public static String formPost(CloseableHttpClient httpClient,String urlStr, Map<String, Object> paramsMap, Map<String, Object> headers) {
        try {
            List<NameValuePair> nvps = new ArrayList<>();
            if (MapUtil.isNotEmpty(paramsMap)) {
                for (Map.Entry<String, Object> stringObjectEntry : paramsMap.entrySet()) {
                    nvps.add(new BasicNameValuePair(stringObjectEntry.getKey(), stringObjectEntry.getValue().toString()));
                }
            }
            nvps.addAll(getQueryParams(urlStr));

            log.info("请求地址为：{}", urlStr);
            HttpPost httpPost = new HttpPost(urlStr);
            httpPost.setEntity(new UrlEncodedFormEntity(nvps));

            addHeader(httpPost, headers);
            CloseableHttpResponse closeableHttpResponse = httpClient.execute(httpPost);
            HttpEntity entity = closeableHttpResponse.getEntity();
            String res = IoUtil.read(entity.getContent(), StandardCharsets.UTF_8);
            closeableHttpResponse.close();
            return res;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static List<? extends NameValuePair> getQueryParams(String url) {
        List<NameValuePair> nvps = new ArrayList<>();
        int index = url.indexOf("?");
        if(index != -1 &&index <url.length()-1){
            String querys = url.substring(index + 1);
            String[] split = querys.split("&");
            for (String s : split) {
                String[] kv = s.split("=");
                if(kv.length == 2){
                    nvps.add(new BasicNameValuePair(kv[0],kv[1]));
                }
            }
        }
        return nvps;
    }


    public static String postJson(String url, Map<String, Object> headers, String body) {
        return postJson(httpClient,url,headers,body);
    }

    public static String postJson(CloseableHttpClient httpClient,String url, Map<String, Object> headers, String body) {
        HttpPost hp = new HttpPost(url);
        //设置数据为utf-8编码
        StringEntity entity = new StringEntity(body, ContentType.APPLICATION_JSON);
        hp.setEntity(entity);
        addHeader(hp,headers);
        try (CloseableHttpResponse result = httpClient.execute(hp)){
            String trim = EntityUtils.toString(result.getEntity(), StandardCharsets.UTF_8).trim();
            result.close();
            return trim;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String getJson(CloseableHttpClient httpClient,String url, Map<String, Object> headers, String body) {
        HttpGet hp = new HttpGet(url);
        //设置数据为utf-8编码
        StringEntity entity = new StringEntity(body, ContentType.APPLICATION_JSON);
        hp.setEntity(entity);
        addHeader(hp,headers);
        try (CloseableHttpResponse result = httpClient.execute(hp)){
            String trim = EntityUtils.toString(result.getEntity(), StandardCharsets.UTF_8).trim();
            result.close();
            return trim;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void downloadFile(String url, File file) throws IOException {
        HttpGet httpGet = new HttpGet(url);
        CloseableHttpResponse response = httpClient.execute(httpGet);
        HttpEntity entity = response.getEntity();
        try(InputStream content = entity.getContent()) {
            FileUtil.writeFromStream(content,file);
        }
    }
    public static String uploadFile(String url, String filePath) {
        try {
            // 创建 POST 请求
            HttpPost httpPost = new HttpPost(url);

            // 构建文件实体
            File file = new File(filePath);
            HttpEntity fileEntity = MultipartEntityBuilder.create()
                    .setMode(HttpMultipartMode.LEGACY)
                    .addBinaryBody("file", file, ContentType.DEFAULT_BINARY, file.getName())
                    .build();

            // 设置请求实体
            httpPost.setEntity(fileEntity);

            // 执行请求
            CloseableHttpResponse result = httpClient.execute(httpPost);
            String trim = EntityUtils.toString(result.getEntity(), StandardCharsets.UTF_8).trim();
            result.close();
            return trim;
        }catch (Exception e){
            throw new RuntimeException(e);
        }

    }

    public static String uploadFile(String url, byte[] data) {
        return uploadFile(url,data,null);
    }

    public static String uploadFile(String url, byte[] data,Map<String,Object> headers) {
        try {
            log.info("upload file url={}",url);
            // 创建 POST 请求
            HttpPost httpPost = new HttpPost(url);
            addHeader(httpPost,headers);
            HttpEntity fileEntity = MultipartEntityBuilder.create()
                    .setMode(HttpMultipartMode.LEGACY)
                    .addBinaryBody("file", data, ContentType.DEFAULT_BINARY,"1111")
                    .build();

            // 设置请求实体
            httpPost.setEntity(fileEntity);

            // 执行请求
            CloseableHttpResponse result = httpClient.execute(httpPost);
            String trim = EntityUtils.toString(result.getEntity(), StandardCharsets.UTF_8).trim();
            result.close();
            return trim;
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    private static void addHeader(HttpUriRequestBase requestBase, Map<String, Object> headers) {
        if(MapUtil.isNotEmpty(headers)){
            headers.forEach((k,v)->{
                requestBase.addHeader(k,v.toString());
            });
        }
    }

    public static byte[] getContent(String url) {
        HttpGet httpGet = new HttpGet(url);
        try (
                CloseableHttpResponse closeableHttpResponse = httpClient.execute(httpGet);
                HttpEntity entity = closeableHttpResponse.getEntity();
                InputStream content = entity.getContent()) {
            return IoUtil.readBytes(content);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static class NopCookieStore implements CookieStore{

        @Override
        public void addCookie(Cookie cookie) {

        }

        @Override
        public List<Cookie> getCookies() {
            return Collections.emptyList();
        }

        @Override
        public boolean clearExpired(Date date) {
            return false;
        }

        @Override
        public void clear() {

        }
    }
}
